package file;


/**
 * Author: mb25428
 * Create Date:  3/23/2013
 * 
 * Comments: this java class is for the image encrypt and decryption
 * JDK version: <JDK 1.7>
 * 
 * Modified By: mb25428
 * Modified Date: 4/3/2013
 * Why&What is Modified: Add some image enhance controller
 * 
 */

import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.faces.context.FacesContext;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpSession;

import org.primefaces.event.SlideEndEvent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;

import common.ImageBean;
import common.UserBean;



public class ImageEnhanceController {
	
	private StreamedContent oriImage;
	private StreamedContent encryptImage;
	private int enhanceParam;
	private StreamedContent downloadImage;
	private StreamedContent enhanceImage;
	
	
	
	//this is for encrypt
	private static HashMap<Integer, Integer> keyMap = new HashMap<Integer, Integer>();
	private static Map<Integer, Integer> imageMap = new HashMap<Integer, Integer>();
	private static List<Integer> keyList = new ArrayList<Integer>();
	
	
	

	public int getEnhanceParam() {
		return enhanceParam;
	}

	
	public void setEnhanceParam(int enhanceParam) {
		this.enhanceParam = enhanceParam;
	}

	public StreamedContent getEncryptImage() {
		return encryptImage;
	}

	public void setEncryptImage(StreamedContent encryptImage) {
		this.encryptImage = encryptImage;
	}

	public StreamedContent getOriImage() {
		return oriImage;
	}

	public void setOriImage(StreamedContent oriImage) {
		this.oriImage = oriImage;
	}

	
	

	public StreamedContent getEnhanceImage() {
		return enhanceImage;
	}

	public void setEnhanceImage(StreamedContent enhanceImage) {
		this.enhanceImage = enhanceImage;
	}
	
	
	
	
	public StreamedContent getDownloadImage() {
		return downloadImage;
	}

	public void setDownloadImage(StreamedContent downloadImage) {
		this.downloadImage = downloadImage;
	}

	public void enhanceImageOne(){
		System.out.println("enhance image");
	}
	
	
	public void downEnhanceImage(){
		HttpSession session = (HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(true);
		FileUploadController f = (FileUploadController) session.getAttribute("fileUploadController");
		oriImage = f.getFile();
	}
	
	
	public ImageBean getImageBean(String attribute){
		HttpSession session = (HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(true);
		FileUploadController f = (FileUploadController) session.getAttribute("fileUploadController");

		UserBean userBean = f.getUserBean();
		return userBean.getOriImage();
	}
	/**
	 * Gray Image
	 */
	public void enhanceImageGray(){
		
		ImageBean oriImage = getImageBean("fileUploadController");
		
		BufferedImage bufferedImage = oriImage.getBuferedImage();
		
		
		int width = bufferedImage.getWidth();
		int height = bufferedImage.getHeight();
		
		int imageData[] = bufferedImage.getRGB(0, 0, width, height, null, 0, width);
		 
		System.out.println(bufferedImage.getType() + " type");
		System.out.println(BufferedImage.TYPE_INT_BGR);
		
		ByteArrayOutputStream fos =  new ByteArrayOutputStream();
		BufferedImage img = new BufferedImage(width, height,BufferedImage.TYPE_INT_ARGB);
		img.setRGB(0, 0, width, height, imageData, 0, width);
		img.flush();
		
		BufferedImage img3 = ImageProcess.processGrayImage(bufferedImage);
		
		byte[] nextImage = null;
		try {
			ImageIO.write(img3, "jpg", fos);
			nextImage = fos.toByteArray();
			fos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		String name = oriImage.getName();
		String contentType = oriImage.getContentType();
		
		enhanceImage = new DefaultStreamedContent(new ByteArrayInputStream(nextImage),contentType, name);
		downloadImage = new DefaultStreamedContent(new ByteArrayInputStream(nextImage),contentType, name);
	}
	
	
	
	public void enhanceImage(SlideEndEvent event){
		
		int value = event.getValue();
		System.out.println("The silder value is "+event.getValue());
		HttpSession session = (HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(true);
		FileUploadController f = (FileUploadController) session.getAttribute("fileUploadController");
	
		UserBean userBean = f.getUserBean();
		ImageBean oriImage = userBean.getOriImage();
		
		BufferedImage bufferedImage = oriImage.getBuferedImage();
		
		System.out.println("the ori image type"+bufferedImage.getType() + " " + BufferedImage.TYPE_INT_RGB);
		
		int width = bufferedImage.getWidth();
		int height = bufferedImage.getHeight();
		
		
		int newImageData[] = new int[width*height];
		int imageData[] = bufferedImage.getRGB(0, 0, width, height, null, 0, width);
		  
		int rData[] = new int[width*height];
		int gData[] = new int[width*height];
		int bData[] = new int[width*height];
		
		for(int i=0;i<imageData.length;i++)
		{
		   rData[i] = (imageData[i] & 0xff0000) >> 16;
		   gData[i] = (imageData[i] & 0xff00) >> 8;
		   bData[i] = (imageData[i] & 0xff) ;
		}
		
		// enhancement
		for (int v = 1; v <= height - 2; v++) {
		   for (int u = 1; u <= width - 2; u++) {

				int f1 = 0;
				int f2 = 0;
				int f3 = 0;
				
				f1 = 4* rData[v*width + u] - rData[v*width + u -1]-rData[v*width + u+1]-rData[(v-1)*width + u]-rData[(v-1)*width+u];
				f2 = 4* gData[v*width + u] - gData[v*width + u -1]-gData[v*width + u+1]-gData[(v-1)*width + u]-gData[(v-1)*width+u];
				f3 = 4* bData[v*width + u] - bData[v*width + u -1]-bData[v*width + u+1]-bData[(v-1)*width + u]-bData[(v-1)*width+u];
				
				
				int q1 = rData[v*width+u] + value*f1/100;
				int q2 = gData[v*width+u] + value*f2/100;
				int q3 = bData[v*width+u] + value*f3/100;
				
				newImageData[v * width + u] =  (255 << 24) | (q1 << 16) | (q2 <<8 )| q3;//新图

		   	}
		 }
		
		
		ByteArrayOutputStream fos =  new ByteArrayOutputStream();
		BufferedImage img = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
		img.setRGB(0, 0, width, height, newImageData, 0, width);
		img.flush();
		
		
		byte[] nextImage = null;
		try {
			ImageIO.write(img, "jpg", fos);
			nextImage = fos.toByteArray();
			fos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
		
		String name = oriImage.getName();
		String contentType = oriImage.getContentType();
		
		enhanceImage = new DefaultStreamedContent(new ByteArrayInputStream(nextImage),contentType, name);
		downloadImage = new DefaultStreamedContent(new ByteArrayInputStream(nextImage),contentType, name);
	}
	

	/**
	 * decrypt Image
	 */
	public void decryptImage(){
		HttpSession session = (HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(true);
		FileUploadController f = (FileUploadController) session.getAttribute("fileUploadController");

		UserBean userBean = f.getUserBean();
		ImageBean oriImage = userBean.getOriImage();
		
		BufferedImage bufferedImage = oriImage.getBuferedImage();

		
		int width = bufferedImage.getWidth();
		int height = bufferedImage.getHeight();
		
		
		int newImageData[] = new int[width*height];
		int imageData[] = bufferedImage.getRGB(0, 0, width, height, null, 0, width);
		
		int size = width*height;
		Collections.sort(keyList);
		
		for(int i =0;i < size;i++){
			newImageData[(Integer) keyMap.get(keyList.get(i))] = imageData[i];
		}
		
		ByteArrayOutputStream fos =  new ByteArrayOutputStream();
		BufferedImage img = new BufferedImage(width, height,BufferedImage.TYPE_3BYTE_BGR);
		img.setRGB(0, 0, width, height, newImageData, 0, width);
		img.flush();
		
		
		byte[] nextImage = null;
		try {
			ImageIO.write(img, "jpg", fos);
			nextImage = fos.toByteArray();
			fos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		String name = oriImage.getName();
		String contentType = oriImage.getContentType();
		
		enhanceImage = new DefaultStreamedContent(new ByteArrayInputStream(nextImage),contentType, name);
		downloadImage = new DefaultStreamedContent(new ByteArrayInputStream(nextImage),contentType, name);
	}
	
	
	/**
	 * Encrypt Image 
	 */

	public void encryptImage(){
		HttpSession session = (HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(true);
		FileUploadController f = (FileUploadController) session.getAttribute("fileUploadController");

		UserBean userBean = f.getUserBean();
		ImageBean oriImage = userBean.getOriImage();
		
		BufferedImage bufferedImage = oriImage.getBuferedImage();
		
		int width = bufferedImage.getWidth();
		int height = bufferedImage.getHeight();
		
		
		int newImageData[] = new int[width*height];
		int imageData[] = bufferedImage.getRGB(0, 0, width, height, null, 0, width);
		
		int size = width*height;
		
		//Map map = new HashMap();
//    	int n =Integer.MAX_VALUE;
    	Random rand =new Random();
    	boolean[] bool = new boolean[15897285];
    	
    	//List list = new ArrayList();
    	keyList.clear();
    	
    	int randInt = 0;
    	for(int i =0;i < size;i++){
    		do{
    			randInt = rand.nextInt(15897285);
    			//System.out.println(randInt);
    		}while(bool[randInt]);
    		//System.out.println(imageData[i]);
    		keyMap.put(randInt, i);
    		imageMap.put(randInt, imageData[i]);
    		//System.out.println(imageData[i]+"  "+imageMap.get(randInt));
    		keyList.add(randInt);
    		bool[randInt] = true;
    	}
    	
    	Collections.sort(keyList);
    	
    	
    	int newImageData1[] = new int[width*height];
    	for(int i =0;i < size;i++){
				newImageData[i] = imageData[keyMap.get(keyList.get(i))];
		}
    	for(int i =0;i < size;i++){
    		newImageData1[(Integer) keyMap.get(keyList.get(i))] = newImageData[i];
    	}
 
    
    	
    	ByteArrayOutputStream fos =  new ByteArrayOutputStream();
		BufferedImage img = new BufferedImage(width, height,BufferedImage.TYPE_3BYTE_BGR);
		img.setRGB(0, 0, width, height, newImageData, 0, width);
		img.flush();
		
		
		byte[] nextImage = null;
		try {
			ImageIO.write(img, "jpg", fos);
			nextImage = fos.toByteArray();
			fos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
		
		String name = oriImage.getName();
		String contentType = oriImage.getContentType();
		
		enhanceImage = new DefaultStreamedContent(new ByteArrayInputStream(nextImage),contentType, name);
		downloadImage = new DefaultStreamedContent(new ByteArrayInputStream(nextImage),contentType, name);
	}
	
	/**
     * Convert the RGB image to the gray image 
     * @param srcImageFile : the address of source Image file
     * @param destImageFile the address of destination Image file
     */
    public final static void gray(String srcImageFile, String destImageFile) {
        try {
            BufferedImage src = ImageIO.read(new File(srcImageFile));
            ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
            ColorConvertOp op = new ColorConvertOp(cs, null);
            src = op.filter(src, null);
            ImageIO.write(src, "JPEG", new File(destImageFile));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public void enhanceImageEdge(){
    	
    	ImageBean oriImage = getImageBean("fileUploadController");	
		
		BufferedImage img = ImageProcess.edgeEnhance(oriImage.getBuferedImage());
		
		saveImage(oriImage,img);
		
	}
    
    public void enhanceImageSharpen(){
    	ImageBean oriImage = getImageBean("fileUploadController");	
		
		BufferedImage img = ImageProcess.sharpen(oriImage.getBuferedImage());
		
		saveImage(oriImage,img);
		
	}

	public void enhanceImageBlurs(){
		
		ImageBean oriImage = getImageBean("fileUploadController");	
		
		BufferedImage img = ImageProcess.blurs(oriImage.getBuferedImage());
		
		saveImage(oriImage,img);
		
	}
	
	public void enhanceImageAnaglyph(){
		ImageBean oriImage = getImageBean("fileUploadController");	
		
		BufferedImage img = ImageProcess.anaglyph(oriImage.getBuferedImage());
		
		saveImage(oriImage,img);
		
	}
	
	
	public void enhanceImageEdgeDetect(){
		
		ImageBean oriImage = getImageBean("fileUploadController");	
		
		BufferedImage img = ImageProcess.edgeDetect(oriImage.getBuferedImage());
		
		saveImage(oriImage,img);
		
	}
	
	public void saveImage(ImageBean oriImage,BufferedImage img){
		
		ByteArrayOutputStream fos =  new ByteArrayOutputStream();
		byte[] nextImage = null;
		try {
			ImageIO.write(img, "jpg", fos);
			nextImage = fos.toByteArray();
			fos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		String name = oriImage.getName();
		String contentType = oriImage.getContentType();
		
		enhanceImage = new DefaultStreamedContent(new ByteArrayInputStream(nextImage),contentType, name);
		downloadImage = new DefaultStreamedContent(new ByteArrayInputStream(nextImage),contentType, name);
	}
}
